<script lang="ts" setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { io, Socket } from "socket.io-client";
import { Stream } from 'stream';

const called = ref<boolean>(false) // 是否是接收方
const caller = ref<boolean>(false) // 是否是发起方
const calling = ref<boolean>(false) // 呼叫中
const communicating = ref<boolean>(false) // 视频通话中
const localVideo = ref<HTMLVideoElement>() // video标签实例，播放本人的视频
const remoteVideo = ref<HTMLVideoElement>() // video标签实例，播放对方的视频
const peer = ref<any>()
const localStream=ref<any>()

const socket = ref<Socket>() // Socket实例
const roomId = '001'
  onMounted(() => {
    const sock = io('localhost:3000'); // 对应服务的端口
    
    // 连接成功
    sock.on('connectionSuccess', () => {
      console.log('连接成功')
      sock.emit('joinRoom', roomId) // 前端发送加入房间事件
    });
    sock.on('callRemote',()=>{
      if(!caller.value){
        called.value=true
        calling.value=true
      }
    })
    sock.on('acceptCall',async()=>{
      if(caller.value){
        peer.value=new RTCPeerConnection()
        // 添加本地音视频流
        peer.value.addStream(localStream.value)

        // 通过监听onicecandidate事件获取candidate信息
        peer.value.onicecandidate = (event: any) => {
          if (event.candidate) {
          console.log('用户A获取candidate信息', event.candidate);
          // 通过信令服务器发送candidate信息给用户B
          socket.value?.emit('sendCandidate', {
            roomId,
            candidate: event.candidate
          })
        }
      }


        // 监听onaddstream来获取对方的音视频流
        peer.value.onaddstream = (event: any) => {
          console.log('a get b',event.stream);
          calling.value = false;
          communicating.value = true;
          remoteVideo.value!.srcObject = event.stream
          remoteVideo.value!.play()
      }



        // 生成offer
        const offer = await peer.value.createOffer({
          offerToReceiveAudio: 1,
          offerToReceiveVideo: 1
        })
        console.log('offer', offer);

        // 设置本地描述的offer
        await peer.value.setLocalDescription(offer);
        // 通过信令服务器将offer发送给用户B
        socket.value?.emit('sendOffer', { offer, roomId })
      }
    })

   

    sock.on('sendOffer', async(offer) => {
      if (called.value) { // 判断接收方
      console.log('收到offer', offer);
      
      // 创建自己的RTCPeerConnection
      peer.value = new RTCPeerConnection()
      // 添加本地音视频流
      const stream = await getLocalStream()
      peer.value.addStream(stream)


      peer.value.onicecandidate = (event: any) => {
        if (event.candidate) {
          console.log('用户B获取candidate信息', event.candidate);
          // 通过信令服务器发送candidate信息给用户A
          socket.value?.emit('sendCandidate', {
            roomId,
            candidate: event.candidate
          })
        }
      }

        // 监听onaddstream来获取对方的音视频流
        peer.value.onaddstream = (event: any) => {
          console.log('b get a',event.stream);
          calling.value = false;
          communicating.value = true;
          remoteVideo.value!.srcObject = event.stream
          remoteVideo.value!.play()
      }


      // 设置远端描述信息
      await peer.value.setRemoteDescription(offer);
      const answer = await peer.value.createAnswer()
      console.log('b has answer',answer);
      await peer.value.setLocalDescription(answer);
      // 发送answer给信令服务器
      socket.value?.emit('sendAnswer', { answer, roomId })
      }
    })

    
    sock.on('sendAnswer', async(answer) => {
      if (caller.value) { // 判断是否是发送方
        console.log('A is get the answer',answer);
        // 设置远端answer信息
        await peer.value.setRemoteDescription(answer);
      }
    })


    // 添加candidate信息
    sock.on('sendCandidate', async (candidate) => {
      console.log('candidate is get',candidate);
      await peer.value.addIceCandidate(candidate);
    })

    sock.on('hangUp',()=>{
      reset();
    })


    socket.value = sock;
  })

// 获取本地音视频流
const getLocalStream = async () => {
  const stream = await navigator.mediaDevices.getUserMedia({ // 获取音视频流
    audio: true,
    video: true
  })

  localVideo.value!.srcObject = stream
  localVideo.value!.play()
  localStream.value=stream
  return stream
}


// 发起方发起视频请求
const callRemote = async() => {
  console.log('发起视频');
  caller.value = true;
  calling.value = true;
  await getLocalStream()
	// 向信令服务器发送发起请求的事件
  socket.value?.emit('callRemote', roomId)

}

// 接收方同意视频请求
const acceptCall = () => {
  console.log('同意视频邀请');

  socket.value?.emit('acceptCall', roomId)
}


// 挂断视频
const hangUp = () => {
  console.log('挂断视频');
  socket.value?.emit('hangUp', roomId);
}

// 状态复原
const reset = () => {
  called.value = false
  caller.value = false
  calling.value = false
  communicating.value = false
  peer.value = null
  localVideo.value!.srcObject = null
  remoteVideo.value!.srcObject = null
  localStream.value = undefined
}





</script>

<template>
  <div class="flex items-center flex-col text-center p-12 h-screen">
    <div class="relative h-full mb-4">
      <video
        ref="localVideo" 
        class="w-96 h-full bg-gray-200 mb-4 object-cover"
      ></video>
      <video
        ref="remoteVideo"
        class="w-32 h-48 absolute bottom-0 right-0 object-cover"
      ></video>
      <div v-if="caller && calling" class="absolute top-2/3 left-36 flex flex-col items-center">
        <p class="mb-4 text-white">等待对方接听...</p>
        <img @click="hangUp" src="/guaDuang.png" class="w-16 cursor-pointer" alt="">
      </div>
      <div v-if="called && calling" class="absolute top-2/3 left-32 flex flex-col items-center">
        <p class="mb-4 text-white">收到视频邀请...</p>
        <div class="flex">
          <img @click="hangUp" src="/guaDuang.png" class="w-16 cursor-pointer mr-4" alt="">
          <img @click="acceptCall" src="/jieTing.png" class="w-16 cursor-pointer" alt="">
        </div>
      </div>
    </div>
    <div class="flex gap-2 mb-4">
      <button 
        class="rounded-md bg-indigo-600 px-4 py-2 text-sm font-semibold text-white" 
        @click="callRemote"
      >发起视频</button>
      <button 
        class="rounded-md bg-red-600 px-4 py-2 text-sm font-semibold text-white" 
        @click="hangUp"
      >挂断视频</button>
    </div>
  </div>
</template>
